package com.song.common.utils;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.song.common.constants.CacheConstant;
import com.song.common.domain.vo.LoginUserVO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class JwtUtil {

    private static final String SECRET = "fagasdfaggsfafdgnfdau";

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    /**
     * 创建token
     */
    public String createToken(LoginUserVO loginUserVO) {
        String token = UUID.randomUUID().toString().replace("-", "");
        // 将token存储到登录用户中，可以在后台系统中根据token值来获取存储在redis中的数据
        loginUserVO.setToken(token);
        // 设置登录用户当前登录时间
        loginUserVO.setLoginTime(System.currentTimeMillis());
        // 将用户信息存储到Redis中，Key：token， Value：loginUserVO
        refreshToken(loginUserVO);

        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("token", token);
        return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, SECRET).compact();
    }

    /**
     * 解析token
     * token： jwt字符串 *******.********.****
     */
    public Claims parseToken(String token) {
        return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
    }

    public LoginUserVO getLoginUser(HttpServletRequest request) {
        // 通过jwt加密的token
        String token = request.getHeader("Daocao-Authorization");
        if (ObjectUtil.isNotNull(token)) {
            // 解析token
            Claims claims = parseToken(token);
            // 解析过的token
            String parseToken = (String) claims.get("token");
            // 根据token从Redis中获取数据
            LoginUserVO loginUserVO = redisCacheUtil.getCacheObject(CacheConstant.LOGIN_USER_KEY + parseToken);
            if (ObjectUtil.isNotNull(loginUserVO)) {
                if ((System.currentTimeMillis() - loginUserVO.getLoginTime()) <= 1000 * 60 * 10) {
                    // 刷新token
                    refreshToken(loginUserVO);
                }
                return loginUserVO;
            }
            return null;
        }
        return null;
    }

    // 刷新token
    private void refreshToken(LoginUserVO loginUserVO) {
        redisCacheUtil.setCacheObject(CacheConstant.LOGIN_USER_KEY + loginUserVO.getToken(), loginUserVO, 30, TimeUnit.MINUTES);
    }
}
